import G6 from "@antv/g6";
import EventBus from "./events";

G6.registerBehavior('add-edge', {
  getEvents() {
    return {
      'node:click': 'onClick',
      'combo:click': 'onClick',
      mousemove: 'onMouseMove',
      // 点击空白处，取消边
      // 因为点击空白处，实质是点击在边上
      'edge:click': 'onEdgeClick'
    };
  },
  // isChildOf(node, combo) {

  // },
  onEnd(model) {
    const graph = this.graph
    const source = this.edge.getModel().source
    const target = model.id
    // 不允许连线自环
    if (source === target) {
      // eslint-disable-next-line
      console.debug(`The edge is a loop, abort!`)
      graph.removeItem(this.edge);
      this.edge = null;
      this.addingEdge = false;
      return
    }
    // 如果边已经存在，则取消此操作
    // 禁止两个节点间连接多条线
    if (graph.find('edge', item => {
      const itemModel = item.getModel()
      return (itemModel.source === source && itemModel.target === target) ||
        (itemModel.source === target && itemModel.target === source)
    })) {
      // eslint-disable-next-line
      console.debug(`The edge from ${source} to ${target} is duplicated, abort!`)
      graph.removeItem(this.edge);
      this.edge = null;
      this.addingEdge = false;
      return
    }

    const defaultStyle = graph.cfg.defaultEdge.style
    graph.updateItem(this.edge, {
      target: target,
      style: {
        ...defaultStyle
      }
    });
    this.edge.toFront()
    graph.emit('custom:add-edge', {
      item: this.edge
    })
    // graph.setItemState(this.edge, 'selected', true);
    this.edge = null;
    this.addingEdge = false;
  },
  onClick(ev) {
    const node = ev.item;
    const graph = this.graph;
    const point = {
      x: ev.x,
      y: ev.y
    };
    // function cancel(e) {
    //   if (e.keyCode === 27) {
    //     window.removeEventListener('keydown', cancel)
    //     // ESC 取消连线
    //     graph.removeItem(this.edge);
    //     this.edge = null;
    //     this.addingEdge = false;
    //   }
    // }
    const model = node.getModel();
    if (this.addingEdge && this.edge) {
      this.onEnd(model)
    } else {
      // 检查键盘控制键是否按下
      const options = graph.$opts;
      if (options) {
        const controls = options.controls.edge;
        const oe = ev.originalEvent;
        if (controls.ctrl && !oe.ctrlKey) {
          // console.debug('ctrl key required')
          // 需要 ctrl 但未按下
          return
        }
        if (controls.shift && !oe.shiftKey) {
          // console.debug('shift key required')
          // 需要 shift 但未按下
          return
        }
      }
      const option = {
        source: model.id,
        target: point,
        style: {
          ...this.graph.cfg.defaultEdge.style,
          endArrow: true
        }
      }
      let canceled = false
      EventBus.emit('edge:before-add', {
        option,
        cancel: () => {
          canceled = true
        }
      })
      if (canceled) {
        return
      }
      this.edge = graph.addItem('edge', option);
      this.addingEdge = true;
      // window.addEventListener('keydown', cancel)
    }
  },
  onMouseMove(ev) {
    const point = {
      x: ev.x,
      y: ev.y
    };
    if (this.addingEdge && this.edge) {
      this.graph.updateItem(this.edge, {
        target: point
      });

      // 避免边被图形遮挡
      // this.edge.toFront()
    }

    // const item = ev.item
    // if (item) {
    //   // 显示锚点
    //   item.setState('showAnchors', true)
    // }
  },
  onEdgeClick(ev) {
    // 拖拽过程中，点击会点击到新增的边上
    if (!this.addingEdge || this.edge !== ev.item) {
      return
    }

    // 突然出现鼠标始终会点击在线上的问题，在此添加代码片段以处理
    const graph = this.graph
    const { x, y } = graph.getPointByClient(ev.clientX, ev.clientY);

    let targetItem
    const nodes = graph.getNodes()
    for (const node of nodes) {
      const bbox = node.getBBox();
      if (x >= bbox.minX && x <= bbox.maxX && y >= bbox.minY && y <= bbox.maxY) {
        targetItem = node;
        break
      }
    }
    if (!targetItem) {
      const combos = graph.getCombos()
      for (const combo of combos) {
        const bbox = combo.getBBox();
        if (x >= bbox.minX && x <= bbox.maxX && y >= bbox.minY && y <= bbox.maxY) {
          targetItem = combo;
          break
        }
      }
    }

    if (targetItem) {
      this.onEnd(targetItem.getModel())
      return
    }

    // eslint-disable-next-line
    console.debug(`The edge adding is canceled!`)
    this.graph.removeItem(this.edge);
    this.edge = null;
    this.addingEdge = false;
  }
});
